<template>
  <div class="upload-container">
    <div class="up">
        <a-upload-dragger class="padding" ref="upload" :list-type="listType" name="file" :accept="accept" :file-list="fileList" :beforeUpload="beforeUpload" :multiple="props.multiple" :customRequest="customRequest" @remove="removeFile" @preview="handlePreview">
            <div class="upload">
                <div>
                    <p class="ant-upload-drag-icon"><inbox-outlined></inbox-outlined></p>
                </div>
                <div>
                    <p class="ant-upload-text">点击或拖拽至此</p>
                </div>
                <div>
                    <a-progress type="circle" :percent="progress" :size="30" v-if="progress > 0" />
                </div>
            </div>
        </a-upload-dragger>
    </div>
    
    <!-- 预览模态框 -->
    <a-modal 
      :visible="previewVisible" 
      :footer="null" 
      @cancel="handleCancel"
      :title="previewTitle"
      :width="previewType === 'video' || previewType === 'pdf' ? 900 : 520"
    >
      <!-- 图片预览 -->
      <img 
        v-if="previewType === 'image'" 
        alt="preview" 
        style="width: 100%" 
        :src="previewUrl" 
      />
      
      <!-- 视频预览 -->
      <video 
        v-else-if="previewType === 'video'"
        controls
        style="width: 100%; max-height: 500px;"
        :src="previewUrl"
        preload="metadata"
      >
        您的浏览器不支持视频播放。
      </video>
      
      <!-- PDF文件预览 -->
      <div v-else-if="previewType === 'pdf'" class="pdf-preview">
        <iframe 
          :src="pdfEmbedUrl"
          style="width: 100%; height: 600px; border: 1px solid #d9d9d9;"
          frameborder="0"
        >
          <p>您的浏览器不支持PDF预览。<a :href="pdfEmbedUrl" target="_blank">点击这里下载PDF文件</a></p>
        </iframe>
        <div class="pdf-actions" style="text-align: center; margin-top: 12px;">
          <a-space>
            <a-button type="primary" @click="downloadFile">
              <template #icon><download-outlined /></template>
              下载PDF
            </a-button>
            <a-button @click="openPdfInNewTab">
              在新窗口打开
            </a-button>
          </a-space>
        </div>
      </div>
      
      <!-- 其他文件类型显示文件信息 -->
      <div v-else class="file-preview">
        <div class="file-icon">
          <inbox-outlined style="font-size: 64px; color: #999;" />
        </div>
        <div class="file-info">
          <p><strong>文件名：</strong>{{ previewFileName }}</p>
          <p><strong>文件类型：</strong>{{ previewFileType }}</p>
          <p><strong>文件大小：</strong>{{ previewFileSize }}</p>
        </div>
        <div class="file-actions">
          <a-button type="primary" @click="downloadFile">
            下载文件
          </a-button>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script lang="ts" setup>
//antdv地址 https://1x.antdv.com/components/upload-cn/
import { ref, computed, watch, nextTick } from 'vue';
import SparkMD5 from "spark-md5";
import { Base64 } from "js-base64";
import { InboxOutlined, DownloadOutlined } from "@ant-design/icons-vue";
import { UploadTypes, UploadTypesValues } from "./enums";
// @ts-ignore
import Api from "@/api/";
// @ts-ignore
import helper from "@/utils/helper";

defineOptions({
    inheritAttrs: false,
});

const props = defineProps({
    modelValue: {
        type: String,
        default: "",
    },
    multiple: {
        type: Boolean,
        default: false,
    },
    /**
     * 请传入 UploadTypes 枚举
     */
    accept: {
        type: Number,
        default: UploadTypes.All,
    },
    // 添加文件信息回调函数
    onFileInfo: {
        type: Function,
        default: null,
    },
});

// 预览相关状态
const previewVisible = ref(false);
const previewUrl = ref("");
const previewType = ref(""); // 'image', 'video', 'pdf', 'other'
const previewTitle = ref("");
const previewFileName = ref("");
const previewFileType = ref("");
const previewFileSize = ref("");
const fileList  = ref<UploadFileType[]>([]);

// PDF文件预览相关状态
const pdfEmbedUrl = ref("");

// 检测文件类型
const getFileType = (fileName: string): string => {
    const ext = fileName.toLowerCase().split('.').pop() || '';
    
    // 图片类型
    const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'];
    if (imageExts.includes(ext)) {
        return 'image';
    }
    
    // 视频类型
    const videoExts = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv', 'm4v', '3gp'];
    if (videoExts.includes(ext)) {
        return 'video';
    }
    
    // PDF文件类型
    const pdfExts = ['pdf'];
    if (pdfExts.includes(ext)) {
        return 'pdf';
    }
    
    return 'other';
};

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

// 设置PDF文件预览URL
const setupPdfPreviewUrl = (fileUrl: string) => {
    // 直接使用文件URL进行PDF预览
    pdfEmbedUrl.value = fileUrl;
};

// 预览处理函数
const handlePreview = async (file) => {
    const fileType = getFileType(file.name);
    const url = file.url || helper.toApiUrl("file/download2?md5=" + file.md5);
    
    previewType.value = fileType;
    previewUrl.value = url;
    previewFileName.value = file.name;
    previewFileType.value = file.name.split('.').pop()?.toUpperCase() || '未知';
    
    // 获取文件大小（如果有的话）
    if (file.size) {
        previewFileSize.value = formatFileSize(file.size);
    } else {
        previewFileSize.value = '未知';
    }
    
    // 设置预览标题和PDF文件预览URL
    if (fileType === 'image') {
        previewTitle.value = '图片预览';
    } else if (fileType === 'video') {
        previewTitle.value = '视频预览';
    } else if (fileType === 'pdf') {
        previewTitle.value = 'PDF文件预览';
        setupPdfPreviewUrl(url);
    } else {
        previewTitle.value = '文件信息';
    }
    
    previewVisible.value = true;
};

// 关闭预览
const handleCancel = () => {
    previewVisible.value = false;
    previewUrl.value = "";
    previewType.value = "";
    previewTitle.value = "";
    previewFileName.value = "";
    previewFileType.value = "";
    previewFileSize.value = "";
    
    // 重置PDF预览相关状态
    pdfEmbedUrl.value = "";
};

// 下载文件
const downloadFile = () => {
    if (previewUrl.value) {
        window.open(previewUrl.value, '_blank');
    }
};

// 在新窗口打开PDF
const openPdfInNewTab = () => {
    if (pdfEmbedUrl.value) {
        window.open(pdfEmbedUrl.value, '_blank');
    }
};

watch(
    () => props.modelValue,
    (newV, olV) => {
        
        console.log('Upload component - modelValue changed:', newV);
        if (!!newV) {
            //默认加载
            if (fileList.value.length == 0) {
                newV.split(",").forEach(async (v, i, array) => {
                    if (!v) return; // 跳过空值
                    console.log('Loading file with MD5:', v);
                    let name = await Api.file.fileName(v);
                    fileList.value.push({ 
                        uid: `upload-${Date.now()}-${i}`,
                        name: name, 
                        status: "done", 
                        md5: v, 
                        url: helper.toApiUrl("file/download2?md5=" + v),
                        // 添加文件类型信息用于预览判断
                        fileType: getFileType(name)
                    });
                });
            }
        }
    },
    { immediate: true } // 确保初始化时也执行
);

let listType = computed(() => {
    if (props.accept == UploadTypes.Image) {
        return "picture-card";
    }
    return "text";
});

const emit = defineEmits(["update:modelValue", "update"]);
const progress = ref(0);
const accept = computed(() => {
    var exts = UploadTypesValues[String(props.accept)].ext as Array<string>;
    return exts.join(",");
});
 interface UploadFileType {
    uid: string;
    name: string;
    status: string;
    url?: string;
    size?: number;
    md5?: string;
    fileType?: any;
  }

const removeFile = (file: any) => {
    fileList.value = fileList.value.filter((item) => {
        return item.md5 != file.md5;
    });
    updateValue();
};

const updateValue = () => {
    var result = fileList.value.map((item) => {
        return item.md5;
    });
    // 将值传递给父组件
    emit("update:modelValue", result.join(","));
    emit("update", result.join(","));
    // 调试日志
    console.log('Emitting update:modelValue:', result.join(","));
};

const beforeUpload = (file: any) => {
    if (props.accept == UploadTypes.All) {
        return true;
    }
    var exts = UploadTypesValues[String(props.accept)].ext as Array<string>;
    var types = UploadTypesValues[String(props.accept)].mime as Array<string>;
    const isOk = types.indexOf(file.type) != -1;
    if (!isOk) {
        helper.error(`请上传${exts.join(" ")},！`);
    }
    return isOk;
};

// 组件绑定该自定义预上传方法
const customRequest = (File: { file: any; onProgress?: any; onSuccess?: any }) => {
    
    var fileName = File.file.name;
    let fileReader = new FileReader();
    let spark = new SparkMD5.ArrayBuffer();
    fileReader.readAsArrayBuffer(File.file);
    fileReader.onload = async (e) => {
        let buffs = e.target?.result as ArrayBuffer;
        spark.append(buffs);
        //获取MD5
        let md5 = spark.end();
        let hasFile = fileList.value.some((item) => {
            return item.md5 == md5;
        });
        if (hasFile) {
            helper.error("文件已存在!");
            return;
        }
        //切片 1M上传
        var chunckSize = 1 * 1024 * 1024;
        var totalChunk = buffs.byteLength % chunckSize == 0 ? buffs.byteLength / chunckSize : Math.floor(buffs.byteLength / chunckSize) + 1;
        if(totalChunk==0){
            helper.error("请勿传空文档!");
            return;
        }
        for (var i = 0; i < totalChunk; i++) {
            var start = i == 0 ? 0 : chunckSize * i;
            var end = start + chunckSize;
            if (end > buffs.byteLength) {
                end = buffs.byteLength;
            }
            let data = new Uint8Array(buffs.slice(start, end));
            let base64 = Base64.fromUint8Array(data);
            let result = await Api.file.upload({ totalChunk: totalChunk, name: fileName, md5: md5, data: base64, size: buffs.byteLength, currentChunk: i + 1 });
            if (result?.exists == true) {
                helper.toast("秒传成功!");
                progress.value = 100;
                await nextTick(() => {
                    setTimeout(() => {
                        progress.value = 0;
                    }, 1000);
                });
                // File.onProgress({ percent: 100 }, File.file);
                break;
            }
            if (result?.currentSuccess != true) {
                helper.error(result!.msg);
                break;
            }
            //续传
            if (result.lastChunk != -1) {
                i = result.lastChunk;
            }
            progress.value = Math.floor(((i + 1) / totalChunk) * 100);
            // File.onProgress({ percent: ((i + 1) / totalChunk) * 100 }, File.file);
        }
        File.onSuccess({}, File.file);
        await nextTick(() => {
            setTimeout(() => {
                progress.value = 0;
            }, 1000);
        });
        let fileInfo = { 
            uid: `upload-${Date.now()}-${ fileList.value.length}`, 
            name: fileName, 
            status: "done", 
            md5: md5, 
            url: helper.toApiUrl("file/download2?md5=" + md5),
            size: buffs.byteLength,
            fileType: getFileType(fileName)
        };
        if (!props.multiple) {
            fileList.value = [fileInfo];
        } else {
            fileList.value.push(fileInfo);
        }
        updateValue();
        
        // 调用文件信息回调函数
        if (props.onFileInfo && typeof props.onFileInfo === 'function') {
            // 解析文件名和后缀
            const lastDotIndex = fileName.lastIndexOf('.');
            const name = lastDotIndex > 0 ? fileName.substring(0, lastDotIndex) : fileName;
            const suffix = lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1) : '';
            const size = Math.round(buffs.byteLength / 1024); // 转换为KB
            
            // 调用回调函数，传递文件信息
            props.onFileInfo({
                md5: md5,
                fileName: name,
                suffix: suffix,
                size: size,
                fullName: fileName
            });
        }
    };
};
</script>

<style lang="less" scoped>
.up {
    width: calc(100% - 140px);
    ::v-deep span {
        margin: 0 !important;
        padding: 0 !important;
    }
}
.upload {
    display: flex;
    > div {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 30px;
    }
    > div:nth-child(2) {
        flex: 1;
    }
    > div:last-child {
        min-width: 30px;
    }
    p {
        margin: 0 !important;
        padding: 0 !important;
        line-height: 20px;
    }
    span {
        margin: 0 !important;
    }
    .ant-upload-drag-icon {
        span {
            font-size: 30px !important;
        }
    }
    .ant-upload-text {
        font-size: 14px !important;
    }
}

/* 文件预览样式 */
.file-preview {
    text-align: center;
    padding: 20px;
    
    .file-icon {
        margin-bottom: 16px;
    }
    
    .file-info {
        margin-bottom: 20px;
        text-align: left;
        
        p {
            margin: 8px 0;
            line-height: 1.5;
        }
    }
    
    .file-actions {
        margin-top: 16px;
    }
}

/* PDF文件预览样式 */
.pdf-preview {
    .pdf-actions {
        padding: 12px 0;
        border-top: 1px solid #f0f0f0;
        background-color: #fafafa;
        margin: 0 -24px -24px -24px;
        padding: 16px 24px;
    }
}
</style>
